package com.lineage.server.clientpackets;

import com.lineage.config.Config;
import com.lineage.config.ConfigOther;
import com.lineage.echo.ClientExecutor;
import com.lineage.server.datatables.DungeonRTable;
import com.lineage.server.datatables.DungeonTable;
import com.lineage.server.datatables.MapCheckTable;
import com.lineage.server.datatables.MapsTable;
import static com.lineage.server.model.Instance.L1PcInstance.REGENSTATE_MOVE;
import static com.lineage.server.model.skill.L1SkillId.ABSOLUTE_BARRIER;
import static com.lineage.server.model.skill.L1SkillId.MEDITATION;
import com.lineage.server.model.Instance.L1NpcInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.Instance.L1PetInstance;
import com.lineage.server.model.Instance.L1SkinInstance;
import com.lineage.server.model.Instance.L1SummonInstance;
import com.lineage.server.model.L1CastleLocation;
import com.lineage.server.model.L1Character;
import com.lineage.server.model.L1Object;
import com.lineage.server.model.L1Trade;
import com.lineage.server.model.map.L1WorldMap;
import com.lineage.server.serverpackets.S_MoveCharPacket;
import com.lineage.server.serverpackets.S_NPCPack_Skin;
import com.lineage.server.serverpackets.S_NewMaster;
import com.lineage.server.serverpackets.S_ServerMessage;
import com.lineage.server.serverpackets.ServerBasePacket;
import com.lineage.server.templates.L1MapCheck;
import com.lineage.server.types.Point;
import com.lineage.server.utils.CheckUtil;
import com.lineage.server.utils.Teleportation;
import com.lineage.server.utils.log.PlayerLogUtil;
import com.lineage.server.world.World;
import com.lineage.server.world.WorldTrap;
import java.sql.Timestamp;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class C_MoveChar extends ClientBasePacket {
  private static final Log _log = LogFactory.getLog(C_MoveChar.class);
  
	private static final byte HEADING_TABLE_X[] = { 0, 1, 1, 1, 0, -1, -1, -1 };

	private static final byte HEADING_TABLE_Y[] = { -1, -1, 0, 1, 1, 1, 0, -1 };
	
	private static final int CLIENT_LANGUAGE = Config.CLIENT_LANGUAGE;
  
  public static void 玩家穿透(String info) {
    PlayerLogUtil.writeLog("[玩家穿透纪录]", info);
  }
  
  public static void movexy(String info) {
    PlayerLogUtil.writeLog("玩家开通座标纪录", info);
  }
  
  public void start(byte[] decrypt, ClientExecutor client) {
    try {
      read(decrypt);
      L1PcInstance pc = client.getActiveChar();
      if (pc.isDead() || pc.isTeleport())
        return; 
      if (pc.getTradeID() != 0) {
        L1Trade trade = new L1Trade();
        trade.tradeCancel(pc);
      } 
      int locx = 0;
      int locy = 0;
      int heading = 0;
      try {
        locx = readH();
        locy = readH();
        heading = readC();
      } catch (Exception e2) {
        return;
      } 
      pc.killSkillEffectTimer(MEDITATION);
      pc.setCallClanId(0);
      if (!pc.hasSkillEffect(ABSOLUTE_BARRIER))
        pc.setRegenState(REGENSTATE_MOVE); 
      pc.getMap().setPassable((Point)pc.getLocation(), true);
		// 移動前位置
		final int oleLocx = pc.getX();
		final int oleLocy = pc.getY();
		
      int newlocx = locx + HEADING_TABLE_X[heading];
      int newlocy = locy + HEADING_TABLE_Y[heading];
      try {
        boolean isError = false;
        if (locx != oleLocx && locy != oleLocy)
          isError = true; 
        if (pc.isPrivateShop())
          isError = true; 
        if (pc.isParalyzedX())
          isError = true; 
        if (pc.hasSkillEffect(4017))
          isError = true; 
        int minX = MapsTable.get().getStartX(pc.getMapId());
        int minY = MapsTable.get().getStartY(pc.getMapId());
        int maxX = MapsTable.get().getEndX(pc.getMapId());
        int maxY = MapsTable.get().getEndY(pc.getMapId());
        if (newlocx < minX || newlocx > maxX || newlocy < minY || newlocy > maxY)
          isError = true; 
        boolean isPassable = pc.getMap().isOriginalTile(newlocx, newlocy);
        if (!isPassable) {
          int tile = 0;
          if (pc.getMap().isCombatZone(oleLocx, oleLocy)) {
            tile = 47;
          } else if (pc.getMap().isNormalZone(oleLocx, oleLocy)) {
            tile = 15;
          } else if (pc.getMap().isSafetyZone(oleLocx, oleLocy)) {
            tile = 31;
          } 
          L1WorldMap.get().getMap(pc.getMapId()).setTestTile(newlocx, newlocy, tile);
          movexy("IP(" + pc.getNetConnection().getIp() + ")" + "玩家采点座标地图:" + "【 " + pc.getMapId() + 
              " 】 " + "X座标:" + "[" + newlocx + "] Y座标:[" + newlocy + "]区域(" + tile + ")" + " 】" + 
              new Timestamp(System.currentTimeMillis()) + ")。");
          if (pc.isGm())
            pc.sendPackets((ServerBasePacket)new S_ServerMessage("已解除障碍，该点设为可通行。")); 
        } 
        if (!pc.isGm()) {
          boolean isCheck = false;
          List<L1MapCheck> check = MapCheckTable.get().getList();
          Iterator<L1MapCheck> iterator = check.iterator();
          while (iterator.hasNext()) {
            L1MapCheck temp = iterator.next();
            if (pc.getMapId() == temp.getMapid()) {
              if (temp.getStartX() == 0) {
                isCheck = true;
                break;
              } 
              if (pc.getX() >= temp.getStartX() && pc.getX() <= temp.getEndX() && 
                pc.getY() >= temp.getStartY() && pc.getY() <= temp.getEndY()) {
                isCheck = true;
                break;
              } 
            } 
          } 
          if (isCheck) {
            boolean isPassable2 = pc.getMap().isOriginalTile(newlocx, newlocy);
            if (!isPassable2)
              isError = true; 
          } 
        } 
        if (pc.checkPassable(newlocx, newlocy))
          isError = true; 
        if (isError) {
          pc.setTeleportX(pc.getOleLocX());
          pc.setTeleportY(pc.getOleLocY());
          pc.setTeleportMapId(pc.getMapId());
          pc.setTeleportHeading(pc.getHeading());
          Teleportation.teleportation(pc);
          return;
        } 
      } catch (Exception e) {
        _log.error(e.getLocalizedMessage(), e);
      } 
      int result = pc.speed_Attack()
        .checkInterval(AcceleratorChecker.ACT_TYPE.MOVE);
      if (result == 2)
        _log.error("要求角色移动:速度异常(" + pc.getName() + ")"); 
      CheckUtil.isUserMap(pc);
      if (DungeonTable.get().dg(newlocx, newlocy, pc.getMap().getId(), pc))
        return; 
      if (DungeonRTable.get().dg(newlocx, newlocy, pc.getMap().getId(), pc))
        return; 
      pc.setOleLocX(oleLocx);
      pc.setOleLocY(oleLocy);
      pc.getLocation().set(newlocx, newlocy);
      pc.setHeading(heading);
      if (!pc.isGmInvis() && !pc.isGhost() && !pc.isInvisble())
        pc.broadcastPacketAll((ServerBasePacket)new S_MoveCharPacket((L1Character)pc)); 
      pc.setNpcSpeed();
      setNpcSpeed(pc);
      pc.getMap().setPassable((Point)pc.getLocation(), false);
      WorldTrap.get().onPlayerMoved(pc);
      if (pc.getHierarchs() != null && L1CastleLocation.checkInAllWarArea(pc.getX(), pc.getY(), pc.getMapId()))
        pc.getHierarchs().deleteHierarch(); 
      

      if (!ConfigOther.war_pet_summ && !pc.getPetList().isEmpty() && 
        L1CastleLocation.checkInAllWarArea(pc.getX(), pc.getY(), pc.getMapId())) {
        Object[] array;
        int length = (array = pc.getPetList().values().toArray()).length;
        int i = 0;
        while (i < length) {
          Object obj = array[i];
          L1NpcInstance petObject = (L1NpcInstance)obj;
          if (petObject != null) {
            if (petObject instanceof L1PetInstance) {
              L1PetInstance pet = (L1PetInstance)petObject;
              pet.collect(true);
              pc.removePet((L1NpcInstance)pet);
              pet.deleteMe();
            } 
            if (petObject instanceof L1SummonInstance) {
              L1SummonInstance summon = (L1SummonInstance)petObject;
              S_NewMaster packet = new S_NewMaster((L1NpcInstance)summon);
              if (summon != null) {
                if (summon.destroyed())
                  return; 
                summon.Death(null);
              } 
            } 
          } 
          i++;
        } 
      } 
    } catch (Exception exception) {
    
    } finally {
      over();
    } 
  }
  
  private void setNpcSpeed(L1PcInstance pc) {
    Map<Integer, L1SkinInstance> skinList = pc.getSkins();
    if (skinList.size() > 0) {
      Iterator<Integer> iterator = skinList.keySet().iterator();
      while (iterator.hasNext()) {
        Integer gfxid = iterator.next();
        L1SkinInstance skin = skinList.get(gfxid);
        skin.setX(pc.getX());
        skin.setY(pc.getY());
        skin.setMap(pc.getMap());
        skin.setHeading(pc.getHeading());
        if (skin.getMoveType() == 0) {
          Iterator<L1PcInstance> iterator2 = World.get().getVisiblePlayer((L1Object)skin).iterator();
          while (iterator2.hasNext()) {
            L1PcInstance visiblePc = iterator2.next();
            visiblePc.removeKnownObject((L1Object)skin);
          } 
          skin.broadcastPacketAll((ServerBasePacket)new S_NPCPack_Skin(skin));
          continue;
        } 
        skin.setNpcMoveSpeed();
        skin.broadcastPacketAll((ServerBasePacket)new S_MoveCharPacket((L1Character)skin));
      } 
    } 
  }
  
  public String getType() {
    return getClass().getSimpleName();
  }
}
